import { Component, ViewChild, OnInit } from '@angular/core';
import { _HttpClient, ModalHelper, SettingsService } from '@delon/theme';
import { NzNotificationService, NzModalService } from 'ng-zorro-antd';
import { STComponent, STColumn, STColumnTag, STColumnBadge, STData } from '@delon/abc';
import { applyCC } from '@shared';
import { zip } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { SFSchema } from '@delon/form';
import { QuartzEditComponent } from './edit/quartz-edit.component';
import {
  JobLogComponent,
  BADGE_JOB_STATUS,
  BADGE_JOB_EXEC_STATUS,
  TAG_JOB_TYPE,
  TAG_JOB_MISFIRE,
} from './view/job-log.component';
import { QuartzMsgModalComponent } from './msg/quartz-msg-modal.component';

/**
 * 定时作业
 */
@Component({
  selector: 'app-quartz-job',
  templateUrl: './quartz.component.html',
})
export class QuartzJobComponent implements OnInit {
  auth_btn_add = false;
  auth_btn_edit = false;
  auth_btn_del = false;
  auth_btn_shutdown = false;
  auth_btn_start = false;
  auth_btn_refresh = false;
  auth_btn_run = false;
  auth_btn_msg = false;

  search = false;
  url = `/cf/job/sys-job/page`;
  @ViewChild('st', { static: false }) st: STComponent;

  job_status = [];
  job_execute_status = [];
  job_type = [];
  misfire_policy = [];

  searchSchema: SFSchema = {
    properties: {},
  };

  columns: STColumn[] = applyCC([
    { title: '序号', type: 'no' },
    { title: '任务名', index: 'jobName' },
    { title: '任务组', index: 'jobGroup' },
    { title: '任务状态', index: 'jobStatus', type: 'badge', badge: BADGE_JOB_STATUS },
    { title: '执行状态', index: 'jobExecuteStatus', type: 'badge', badge: BADGE_JOB_EXEC_STATUS },
    { title: '首次执行时间', index: 'startTime', ccChecked: false },
    { title: '上次执行时间', index: 'previousTime' },
    { title: '下次执行时间', index: 'nextTime' },
    { title: '类型', index: 'jobType', type: 'tag', tag: TAG_JOB_TYPE },
    { title: '执行路径', index: 'executePath', ccChecked: false },
    { title: '执行文件', index: 'className', ccChecked: false },
    { title: '执行方法', index: 'methodName', ccChecked: false },
    { title: '执行参数', index: 'methodParamsValue', ccChecked: false },
    { title: 'cron表达式', index: 'cronExpression', ccChecked: false },
    { title: '错失策略', index: 'misfirePolicy', type: 'tag', tag: TAG_JOB_MISFIRE },
    { title: '备注', index: 'remark', ccChecked: false },
    {
      title: '操作',
      buttons: [
        {
          text: '发布',
          type: 'del',
          pop: {
            title: '确定发布作业？',
            okType: 'primary',
          },
          click: (record, _modal, comp) => {
            this.http.post(`/cf/job/sys-job/start-job/${record.jobId}`).subscribe(res => {
              if (res.status === 200) {
                this.notice.success('成功', `成功发布作业【${record.jobName}】`);
                comp!.load();
              }
            });
          },
          iif: (item: STColumn) => {
            if (item.jobStatus === '1' || item.jobStatus === '3') {
              return this.auth_btn_start;
            }
            return false;
          },
        },
        {
          text: '暂停',
          type: 'del',
          pop: {
            title: '确定暂停作业？',
            okType: 'danger',
          },
          click: (record, _modal, comp) => {
            this.http.post(`/cf/job/sys-job/shutdown-job/${record.jobId}`).subscribe(res => {
              if (res.status === 200) {
                this.notice.success('成功', `成功暂停作业【${record.jobName}】`);
                comp!.load();
              }
            });
          },
          iif: (item: STColumn) => {
            if (item.jobStatus === '2') {
              return this.auth_btn_shutdown;
            }
            return false;
          },
        },
        {
          text: '执行',
          type: 'del',
          pop: {
            title: '确定立即执行作业一次？',
            okType: 'danger',
          },
          click: (record, _modal, comp) => {
            this.http.post(`/cf/job/sys-job/run-job/${record.jobId}`).subscribe(res => {
              if (res.status === 200) {
                this.confirmServ.success({
                  nzTitle: `操作成功`,
                  nzContent: `成功触发作业【${record.jobName}】一次。作业以异步方式执行，所以请等待4-8分钟(此时间为预估，根据不同作业复杂度，数据量等因素而不同)然后在日志中查看执行结果`,
                  nzOnOk: () => {
                    comp!.load();
                  },
                });
              }
            });
          },
          iif: (item: STColumn) => {
            if (item.jobStatus === '2') {
              return this.auth_btn_run;
            }
            return false;
          },
        },
        {
          text: '编辑',
          type: 'static',
          modal: {
            component: QuartzEditComponent,
            paramsName: 'record',
            params: (record: STData) => {
              return {
                job_status: this.job_status,
                job_execute_status: this.job_execute_status,
                job_type: this.job_type,
                misfire_policy: this.misfire_policy,
              };
            },
          },
          click: 'reload',
          iif: (item: STColumn) => {
            if (item.jobStatus === '2') {
              return false;
            }
            return this.auth_btn_edit;
          },
        },
        {
          text: '删除',
          type: 'del',
          pop: {
            title: '确定删除作业？',
            okType: 'danger',
          },
          click: (record, _modal, comp) => {
            this.http.delete(`/cf/job/sys-job/${record.jobId}`).subscribe(res => {
              if (res.status === 200) {
                this.notice.success('成功', `成功删除作业【${record.jobName}】`);
                comp!.load();
              }
            });
          },
          iif: (item: STColumn) => {
            if (item.jobStatus === '2') {
              return false;
            }
            return this.auth_btn_del;
          },
        },
        {
          text: '更多',
          children: [
            {
              text: '日志',
              type: 'modal',
              icon: 'file-exclamation',
              modal: {
                component: JobLogComponent,
                paramsName: 'record',
                size: 1300,
              },
            },
            {
              text: '通知',
              icon: 'bell',
              type: 'modal',
              modal: {
                component: QuartzMsgModalComponent,
                paramsName: 'record',
              },
              iif: (item: STColumn) => {
                return this.auth_btn_msg;
              },
            },
          ],
        },
      ],
    },
  ]);

  constructor(
    public http: _HttpClient,
    private notice: NzNotificationService,
    private modal: ModalHelper,
    private confirmServ: NzModalService,
    private settings: SettingsService,
  ) {}

  ngOnInit() {
    this.auth_btn_add = this.settings.user.permissions.job_sys_job_add;
    this.auth_btn_edit = this.settings.user.permissions.job_sys_job_edit;
    this.auth_btn_del = this.settings.user.permissions.job_sys_job_del;
    this.auth_btn_shutdown = this.settings.user.permissions.job_sys_job_shutdown_job;
    this.auth_btn_start = this.settings.user.permissions.job_sys_job_start_job;
    this.auth_btn_refresh = this.settings.user.permissions.job_sys_job_refresh_job;
    this.auth_btn_run = this.settings.user.permissions.job_sys_job_run_job;
    this.auth_btn_msg = this.settings.user.permissions.job_sys_job_msg;
    this.init();
  }

  /**
   * 获取作业相关的数据字典
   */
  init() {
    const api = [
      this.http.get(`/cf/admin/dict/type/job_status`),
      this.http.get(`/cf/admin/dict/type/job_execute_status`),
      this.http.get(`/cf/admin/dict/type/job_type`),
      this.http.get(`/cf/admin/dict/type/misfire_policy`),
    ];
    zip(...api)
      .pipe(
        catchError(([job_status, job_execute_status, job_type, misfire_policy]) => {
          return [job_status, job_execute_status, job_type, misfire_policy];
        }),
      )
      .subscribe(([job_status, job_execute_status, job_type, misfire_policy]) => {
        this.job_status = job_status.data;
        this.job_execute_status = job_execute_status.data;
        this.job_type = job_type.data;
        this.misfire_policy = misfire_policy.data;
        this.buildSF();
      });
  }

  buildSF() {
    this.searchSchema = {
      properties: {
        jobName: { type: 'string', title: '任务名' },
        jobGroup: { type: 'string', title: '组名' },
        jobStatus: {
          ui: {
            widget: 'select',
            width: 180,
          },
          type: 'string',
          title: '任务状态',
          enum: this.job_status,
        },
        jobExecuteStatus: {
          ui: {
            widget: 'select',
            width: 180,
          },
          type: 'string',
          title: '执行状态',
          enum: this.job_execute_status,
        },
      },
    };
  }

  addJob() {
    this.modal
      .createStatic(QuartzEditComponent, {
        i: {
          jobId: 0,
        },
        job_status: this.job_status,
        job_execute_status: this.job_execute_status,
        job_type: this.job_type,
        misfire_policy: this.misfire_policy,
      })
      .subscribe(() => this.st.reload());
  }

  refreshJobs() {
    this.confirmServ.confirm({
      nzTitle: `确定刷新作业? 该操作将会清理Quartz池中所有无效作业`,
      nzOnOk: () => {
        this.http.post(`/cf/job/sys-job/refresh-jobs`).subscribe(res => {
          if (res.status === 200) {
            this.notice.success('成功', '成功清理所有【未发布】作业');
            this.st.load();
          }
        });
      },
    });
  }

  startJobs() {
    this.confirmServ.confirm({
      nzTitle: `确定发布所有【未发布】或【暂停】的作业?`,
      nzOnOk: () => {
        this.http.post(`/cf/job/sys-job/start-jobs`).subscribe(res => {
          if (res.status === 200) {
            this.notice.success('成功', '成功发布所有【未发布】或【暂停】作业');
            this.st.load();
          }
        });
      },
    });
  }

  shutdownJobs() {
    this.confirmServ.confirm({
      nzTitle: `确定暂停所有【已发布】的作业?`,
      nzOnOk: () => {
        this.http.post(`/cf/job/sys-job/shutdown-jobs`).subscribe(res => {
          if (res.status === 200) {
            this.notice.success('成功', '成功暂停所有【已发布】作业');
            this.st.load();
          }
        });
      },
    });
  }
}
